package com.educate.service.impl;


import com.educate.common.lang.ProblemRedisNameConst;
import com.educate.dao.ProblemDao;
import com.educate.dao.ProblemLikeDao;
import com.educate.pojo.PreProblem;
import com.educate.pojo.Problem;
import com.educate.service.ProblemService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.DefaultTypedTuple;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * @author xiongyu
 * @date 2021/12/8 17:59
 */

@Service
public class ProblemServiceImpl implements ProblemService {

    /**
     * 热点问题id
     */
    public static List<Integer> hotProblemIds = new ArrayList<>();

    @Autowired
   private ProblemDao problemDao;

    @Autowired
   private ProblemLikeDao problemLikeDao;

    @Autowired
   private RedisTemplate redisTemplate;

    @Transactional(rollbackFor = {RuntimeException.class})
    @Override
    public long addProblem(Problem problem) {
        problem.setUpdatedProblemTime(new Date());
        problem.setCreatedProblemTime(problem.getUpdatedProblemTime());
        problem.setUsername(Long.parseLong(SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString()));
        problemDao.addProblem(problem);
        return problem.getId();
    }

    @Override
    public Problem queryProblemById(long id) {
        return problemDao.queryProblemById(id, Long.parseLong(SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString()));
    }

    @Transactional(rollbackFor = {RuntimeException.class})
    @Override
    public boolean updateProblem(Problem problem) {
        problem.setUpdatedProblemTime(new Date());
        problem.setUsername(Long.parseLong(SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString()));
        return problemDao.updateProblem(problem) == 1;
    }

    @Transactional(rollbackFor = {RuntimeException.class})
    @Override
    public boolean deleteProblem(long id) {
        return problemDao.deleteProblem(id, Long.parseLong(SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString())) == 1;
    }

    @Override
    public List<PreProblem> queryAllProblems() {
        List<Integer> hotProblemIds = getHotProblemIds();
        List<Problem> problems = problemDao.queryAllProblems(hotProblemIds);
        List<PreProblem> preProblems = new ArrayList<>(12);
        return getPreProblems(problems, preProblems);
    }

    @Transactional(rollbackFor = {RuntimeException.class})
    @Override
    public int updateProblemThumbsUp(long problemId, int problemThumbUp) {
        return problemDao.updateProblemThumbsUp(problemId, problemThumbUp);
    }

    @Override
    public List<PreProblem> queryHotProblems() {
        List<Integer> hotProblemIds = getHotProblemIds();
        List<PreProblem> preProblems = null;
        if (hotProblemIds.size() != 0) {
            preProblems = new ArrayList<>(5);
            preProblems = getPreProblems(problemDao.queryHotProblems(hotProblemIds), preProblems);
        }
        return preProblems;
    }

    @Override
    public Problem queryProblem(long problemId) {
        return problemDao.queryProblem(problemId);
    }

    private List<Integer> getHotProblemIds() {
        if (hotProblemIds.size() == 0) {
            /**
             *查出redis排名五条条热点信息
             */
            synchronized (ProblemServiceImpl.class) {
                if (hotProblemIds.size() == 0) {
                    Set problemLikeNumber = redisTemplate.opsForZSet().reverseRangeWithScores(ProblemRedisNameConst.HOTPROBLEM, 0, 4);
                    for (Object o : problemLikeNumber) {
                        if (o != null && ((DefaultTypedTuple) o).getScore() > 0) {
                            hotProblemIds.add((Integer) ((DefaultTypedTuple) o).getValue());
                        }
                    }
                }
            }
        }
        return hotProblemIds;
    }

    private List<PreProblem> getPreProblems(List<Problem> problems, List<PreProblem> preProblems) {
        long username = Long.parseLong(SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString());
        for (Problem problem : problems) {
            PreProblem preProblem = new PreProblem();
            BeanUtils.copyProperties(problem, preProblem);
            preProblem.setProblemId(problem.getId());
            Object likeNum = redisTemplate.opsForHash().get(ProblemRedisNameConst.PROBLEMLIKENUMBER, String.valueOf(problem.getId()));
            if (likeNum != null) {
                preProblem.setThumbsUp(Long.valueOf(String.valueOf(likeNum)));
            } else {
                preProblem.setThumbsUp(0L);
            }
            preProblem.setUserLike(problemLikeDao.queryProblemLike(problem.getId(), username) == 1 ? true : false);
            preProblems.add(preProblem);
        }

        return preProblems;
    }
}
